package com.tony.juc.StampedLock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created with IntelliJ IDEA.
 *
 * @Title: StampedLockDemo
 * @Auther: 皮蛋布丁
 * @Date: 2022/04/09/20:37
 * @Description:
 */
public class StampedLockDemo001 {

    public static void main(String[] args) {

        StampedLockAccount001 account = new StampedLockAccount001("皮蛋布丁", 0); // 定义银行账户信息
        int money[] = new int[]{110, 230, 10_000}; // 定义要存款的金额
        for (int x = 0; x < 10; x++) { // 10个读锁
            new Thread(() -> {
                while (true) {
                    System.out.print(account);
                }
            }, "取款线程 - " + x).start();
        }
        for (int x = 0; x < 2; x++) {  // 2个写锁
            new Thread(() -> {
                for (int y = 0; y < money.length; y++) {
                    account.save(money[y]); // 存款操作
                }
            }, "存款线程 - " + x).start();
        }
    }
}

class StampedLockAccount001 {
    // 模拟银行账户
    private String name; // 账户的名称
    private int asset; // 账户的资金，资金使用整型
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); // 读写锁

    public StampedLockAccount001(String name, int asset) {
        this.name = name;
        this.asset = asset;
    }

    public void save(int asset) { // 向银行账户之中进行存款操作
        this.readWriteLock.writeLock().lock(); // 写入锁定
        try {
            this.asset += asset; // 存款处理
            TimeUnit.SECONDS.sleep(1); // 模拟业务的处理延迟
            System.err.printf("【%s】修改银行资产，当前的资产为：%10.2f%n", Thread.currentThread().getName(), this.asset / 100.0);
        } catch (Exception e) {
        } finally {
            this.readWriteLock.writeLock().unlock(); // 解除锁定
        }
    }

    @Override
    public String toString() {
        this.readWriteLock.readLock().lock(); // 读锁属于共享锁
        try {
            TimeUnit.MILLISECONDS.sleep(200); // 模拟业务延迟
            return String.format("〖%s〗账户名称：%s、账户余额：%10.2f %n", Thread.currentThread().getName(), this.name, this.asset / 100.0);
        } catch (Exception e) {
            return null;
        } finally {
            this.readWriteLock.readLock().unlock(); // 解除锁定
        }
    }
}
